package com.ctgu.tengyun.util;

import com.ctgu.tengyun.exception.TengyunRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtils {
	private static final Logger logger = LoggerFactory.getLogger(StringUtils.class);
	public static final String EMPTY = "";

	public static String MOBILE_REG_EXP = "^[1][1-9][0-9]{9}$";
	public static Pattern MOBILE_PATTER = Pattern.compile(MOBILE_REG_EXP);  
	
	private static final int idcardIW[]={7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
	private static final char idcardSzVerCode[] = new char[]{'1','0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
	
	private static final int[] md5Accii = new int[128];
	static{
		md5Accii['0'] = 1;
		md5Accii['1'] = 1;
		md5Accii['2'] = 1;
		md5Accii['3'] = 1;
		md5Accii['4'] = 1;
		md5Accii['5'] = 1;
		md5Accii['6'] = 1;
		md5Accii['7'] = 1;
		md5Accii['8'] = 1;
		md5Accii['9'] = 1;
		md5Accii['a'] = 1;
		md5Accii['b'] = 1;
		md5Accii['c'] = 1;
		md5Accii['d'] = 1;
		md5Accii['e'] = 1;
		md5Accii['f'] = 1;
		md5Accii['A'] = 1;
		md5Accii['B'] = 1;
		md5Accii['C'] = 1;
		md5Accii['D'] = 1;
		md5Accii['E'] = 1;
		md5Accii['F'] = 1;
	}

	/**
	 * 从字符串描述的数组中剔除固定的内容
	 * @param src 字串串表示的数组
	 * @param rStr 待剔除的内容
	 * @param spliter 字符串数组分割字符
	 * @return
	 */
	public static String removeItem(String src,String rStr,String spliter){
		StringBuilder sb = new StringBuilder();
		String[] temp = src.split(spliter);
		ArrayList<Integer> ar = new ArrayList<Integer>();
		for(int i=0;i<temp.length;i++){
			if(!temp[i].equalsIgnoreCase(rStr) && !ar.contains(Integer.parseInt(temp[i]))){
				sb.append(temp[i]);
				sb.append(spliter);
				ar.add(Integer.parseInt(temp[i]));
			}
		}
		if(sb.length()>0){
			return sb.substring(0, sb.length()-spliter.length());
		}else {
			return null;
		}
	}
	
	public static String replaceItem(String src, String newStr, String tokenizer) {
		src = notNullTrim(src);
		tokenizer = notNullTrim(tokenizer);
		newStr = notNullTrim(newStr);
		
		StringBuilder sb = new StringBuilder();
		int startIndex = 0;
		do {
			int foundIndex = src.indexOf(tokenizer, startIndex);
			if (foundIndex < 0){
				break;
			}else {
				CharSequence span = src.subSequence(startIndex, foundIndex);
				sb.append(span);
				sb.append(newStr);
				startIndex += tokenizer.length() + span.length();
			}
		} while (true);
		
		sb.append(src.substring(startIndex));

		return sb.toString();
	}

	/**
	 * 获得字符串的MD5
	 * @param strP 字符串
	 * @return 字符串MD5
	 */
	public static String toMD5(String strP) {
		byte[] source=null;
		try {
			source = strP.getBytes("UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		String s = null;
		char hexDigits[] = { // 用来将字节转换成 16 进制表示的字符
				'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd','e', 'f' };
		try {
			java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
			md.update(source);
			byte tmp[] = md.digest(); // MD5 的计算结果是一个 128 位的长整数，
			// 用字节表示就是 16 个字节
			char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话，使用两个字符，
			// 所以表示成 16 进制需要 32 个字符
			int k = 0; // 表示转换结果中对应的字符位置
			for (int i = 0; i < 16; i++) { // 从第一个字节开始，对 MD5 的每一个字节
				// 转换成 16 进制字符的转换
				byte byte0 = tmp[i]; // 取第 i 个字节
				str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
				// >>> 为逻辑右移，将符号位一起右移
				str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
			}
			s = new String(str); // 换后的结果转换为字符串
		} catch (Exception e) {
			logger.error("toMD5 error", e);
		}
		return s;
	}

	public static boolean checkMd5Format(String md5Str){
		if( md5Str == null || md5Str.length() != 32 ){
			return false;
		}

		for( int i = 0; i < md5Str.length(); i++){
			int index = md5Str.charAt(i);
			if(index >= md5Accii.length || index < 0 || md5Accii[index] != 1){
				return false;
			}
		}

		return true;
	}

	public static boolean isEmpty(String value) {
		if (null == value) {
			return true;
		}
		for (int length = value.length(), i = 0; i < length; i++) {
			if (' ' != value.charAt(i)) {
				return false;
			}
		}
		return true;
	}

	public static boolean isNotEmpty(String value){
		return  !isEmpty(value);
	}


	public static long getBytesConfigByString(String str) {
        long value = 0;
        str = str.trim().toLowerCase();
        if (!"".equals(str)) {
            if ('m' == str.charAt(str.length() - 1)) {
                value = (long)(Double.parseDouble(str.substring(0,str.length() - 1)) * 1024 * 1024);
            } else if ('g' == str.charAt(str.length() - 1)) {
                value = (long)(Double.parseDouble(str.substring(0,str.length() - 1)) * 1024 * 1024 * 1024);
            } else if ('t' == str.charAt(str.length() - 1)) {
                value = (long)(Double.parseDouble(str.substring(0,str.length() - 1)) * 1024 * 1024 * 1024 * 1024);
            }else if ('k' == str.charAt(str.length() - 1)) {
                value = (long)(Double.parseDouble(str.substring(0,str.length() - 1)) * 1024);
            } else {
                value = (long)Double.parseDouble(str);
            }
        }
        return value;
    }
	
	public static boolean isAllChar(String src, char c){
		if(null == src || src.length()==0){
			return false;
		}
		
		int len = src.length();
		
		for (int i = 0; i<len; i++) {
			if(src.charAt(i) != c){
				return false;
			}
		}
		return true;
	}
	
	public static String notNull(String strTemp) {
		if (strTemp == null) {
			return new String("");
		} else {
			return strTemp;
		}
	}
	
	public static String limitLength(String str, int length){
		if(length <= 0){
			throw new UnsupportedOperationException("limit length error, length must bigger than 0");
		}
		
		if(str == null){
			return null;
		}
		
		String tempStr = str.trim();
		if(tempStr.length() > length){
			return tempStr.substring(0, length);
		}
		return tempStr;
	}
	
	/**
	 * @param str
	 * @param exceedSuffix 超出指定的长度后所追加的字符串
	 * @param length
	 * @return
	 * @description
	 */
	public static String limitLength(String str, String exceedSuffix, int length){
		if(length <= 0){
			throw new UnsupportedOperationException("limit length error, length must bigger than 0");
		}
		
		if(str == null){
			return null;
		}
		
		String tempStr = str.trim();
		if(tempStr.length() > length){
			int suffixLength = notNull(exceedSuffix).length();
			if(length < suffixLength){
				throw new UnsupportedOperationException("exceedSuffix length bigger than limit length, length:" + length + ", exceedSuffix:" + exceedSuffix);
			}
			return tempStr.substring(0, length - suffixLength) + exceedSuffix;
		}
		return tempStr;
	} 

	public static String notNullTrim(String strTemp) {
		if (strTemp == null) {
			return new String("");
		} else {
			return strTemp.trim();
		}
	}

	public static String join(String separator, String ... args) {
		if (notNull(separator).isEmpty()){
			separator = ",";
		}
		
		if (null == args || args.length == 0){
			return new String("");
		}
		
		StringBuffer buffer = new StringBuffer();
		for (String arg : args){
			buffer.append(arg).append(separator);
		}
		
		return buffer.substring(0, buffer.length() - separator.length());
	}

	public static boolean isMobileNumberValid(String phoneNumber) {
		if(StringUtils.isEmpty(phoneNumber)) {
			return false;
		}
		
		Matcher m = MOBILE_PATTER.matcher(phoneNumber); 
		return m.find();
	}
	
	public static List<Integer> parseIntList(String strs, String separator){
		separator = (null ==  separator) ? "": separator;
		strs = (null == strs) ? "":strs;
		String array[] = strs.split(separator);
		List<Integer> ints = new ArrayList<>(array.length);
		for (int i = 0; i < array.length; i++) {
			String tint = notNullTrim(array[i]);
			if (!tint.isEmpty()){
				ints.add(Integer.valueOf(tint));	
			}
		}
		
		return ints;
	}
	
	/**
	 * @param string 
	 * @param startIndex inclusive
	 * @param endIndex exclusive
	 * @return
	 */
	public static String replace(String string, int startIndex, int endIndex, String str) {
		if (string == null || string.length() < startIndex + 1){
			return string;
		}else if (string.length() < endIndex) {
			StringBuilder buffer = new StringBuilder();
			buffer.append(string.substring(0, startIndex));
			for (int i = string.length(); i > startIndex; i--){
				buffer.append(str);
			}
			return buffer.toString();
		}else {
			StringBuilder buffer = new StringBuilder();
			buffer.append(string.substring(0, startIndex));
			for (int i = endIndex; i > startIndex; i--){
				buffer.append(str);
			}
			buffer.append(string.substring(endIndex));
			return buffer.toString();
		}
	}
	
	public static String getDefaultNicknameFromMobileNumber(String phoneNumber){
		return replace(phoneNumber, 3, 8, "*");
	}

	public static String getMaskFromMobileNumber(String phoneNumber){
		return replace(phoneNumber, 3, 7, "*");
	}

	public static String trim(String str, int maxLength) {
		if (null == str){
			return "";
		}
		
		str =  str.trim();
		if (str.length() <= maxLength){
			return str;
		}else {
			return str.substring(0, maxLength);
		}
	}
	
	public static boolean isIdcardValid(String idcardNo){
		if( StringUtils.isEmpty(idcardNo) || idcardNo.length() != 18 ) {
			return false;
}
		
		char pszSrc[]=idcardNo.toCharArray();
		int iS = 0;
		for(int i=0;i<17;i++) {
			iS += (int)(pszSrc[i]-'0') * idcardIW[i];
		}
		int iY = iS%11;
		return pszSrc[17] == idcardSzVerCode[iY];
	}

	public static final String suffixString(String text, int length){
		if(length <= 0){
			throw new TengyunRuntimeException("invalid length input, length:" + length);
		}

		if(StringUtils.isEmpty(text)){
			return text;
		}

		if(text.length() >= length){
			return text.substring(text.length() - length, text.length());
		}else{
			return text;
		}
	}

	/**
	 * unicode 转字符串
	 */
	public static String unicode2String(String str) {
		Charset set = Charset.forName("UTF-16");
		Pattern p = Pattern.compile("\\\\u([0-9a-fA-F]{4})");
		Matcher m = p.matcher( str );
		int start = 0 ;
		int start2 = 0 ;
		StringBuffer sb = new StringBuffer();
		while( m.find( start ) ) {
			start2 = m.start() ;
			if( start2 > start ){
				String seg = str.substring(start, start2) ;
				sb.append( seg );
			}
			String code = m.group( 1 );
			int i = Integer.valueOf( code , 16 );
			byte[] bb = new byte[ 4 ] ;
			bb[ 0 ] = (byte) ((i >> 8) & 0xFF );
			bb[ 1 ] = (byte) ( i & 0xFF ) ;
			ByteBuffer b = ByteBuffer.wrap(bb);
			sb.append( String.valueOf( set.decode(b) ).trim() );
			start = m.end() ;
		}
		start2 = str.length() ;
		if( start2 > start ){
			String seg = str.substring(start, start2) ;
			sb.append( seg );
		}
		return sb.toString() ;
	}

	public static String trimAllWhitespace(String str) {
		if(!hasLength(str)) {
			return str;
		} else {
			int len = str.length();
			StringBuilder sb = new StringBuilder(str.length());

			for(int i = 0; i < len; ++i) {
				char c = str.charAt(i);
				if(!Character.isWhitespace(c)) {
					sb.append(c);
				}
			}

			return sb.toString();
		}
	}

	public static boolean hasLength(CharSequence str) {
		return str != null && str.length() > 0;
	}

	public static boolean hasLength(String str) {
		return hasLength((CharSequence)str);
	}

	public static int getTrimLength(String s){
		if(s == null){
			return 0;
		}
		return s.trim().length();
	}
}
